﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.ComponentModel;
using Microsoft.TeamFoundation.Framework.Client;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Web.Services.Protocols;
using System.Web.Services;
using Microsoft.TeamFoundation.Server;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Threading;

namespace ShahyadS.TFSBuildInspectionModel
{
	public class BuildDefinitionCollection : SafeObservableCollection<BuildDefinitionRow>, ITFSEventHandlerService, IDisposable
	{
		public IBuildServer BuildServer { get; private set; }
		public TfsTeamProjectCollection TeamProjectCollection { get; private set; }
		public VersionControlServer VersionControlServer { get; private set; }
		public IEventService eventEndpoint { get; private set; }
		public IRegistration RegistrationService { get; private set; }
		private Uri _TeamProjectCollectionUrl;
		private BackgroundWorker bw = new BackgroundWorker();
		public List<BuildDefinitionRow> AllBuildDefinitions = new List<BuildDefinitionRow>();
		public Uri TeamProjectCollectionUrl
		{
			get
			{
				return _TeamProjectCollectionUrl;
			}
			set
			{
				CancelRefresh();
				Items.Clear();
				_TeamProjectCollectionUrl = value;
				TeamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(_TeamProjectCollectionUrl);
				VersionControlServer = (VersionControlServer)TeamProjectCollection.GetService(typeof(VersionControlServer));
				BuildServer = (IBuildServer)TeamProjectCollection.GetService(typeof(IBuildServer));
				eventEndpoint = (IEventService)TeamProjectCollection.GetService(typeof(IEventService));
				RegistrationService = (IRegistration)TeamProjectCollection.GetService(typeof(IRegistration));
				var x = RegistrationService.GetRegistrationEntries(String.Empty);
				var commonStruct = TeamProjectCollection.GetService<ICommonStructureService>();
				var teamProjectInfos = commonStruct.ListAllProjects();
				//compatible with tfs2008
				AllBuildDefinitions = (from p in teamProjectInfos from b in BuildServer.QueryBuildDefinitions(p.Name, QueryOptions.Definitions).Select(b => new BuildDefinitionRow(b, this)) orderby b.Extension descending, b.Line, b.Name select b).ToList();
				foreach (var r in AllBuildDefinitions)
				{
					Items.Add(r);
				}
				OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
				bw.DoWork += new DoWorkEventHandler(bw_DoWork);
				bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
				//publishWebService();
				//TFSEventSubscribe();
			}
		}

		public IQueuedBuild[] AllBuildInQueue;
		public Object[] Agents { get; private set; }
		[SoapDocumentMethod(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", RequestNamespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
		//[WebMethod(MessageName = "Notify")]
		public void Notify(string eventXml, string tfsIdentityXml)
		{
			///todo: refresh the build definition
			throw new NotImplementedException();
		}
		private int tfsEventSubscriptionID = 0;
		private void TFSEventSubscribe()
		{
			DeliveryPreference delPref = new DeliveryPreference();
			delPref.Type = DeliveryType.Soap;
			delPref.Schedule = DeliverySchedule.Immediate;
			delPref.Address = "http://" + System.Environment.MachineName + ":8085/BuildMonitorServices.asmx";
			tfsEventSubscriptionID = eventEndpoint.SubscribeEvent("BuildCompletionEvent2", "\"RequestedFor\" = 'domainName\\ShahyadS'", delPref, "General:BuildCompletionEvent2");
		}
		public BuildDefinitionCollection()
		{
		}
		public BuildDefinitionCollection(string teamProjectCollectionUrl)
		{
			TeamProjectCollectionUrl = new Uri(teamProjectCollectionUrl);
		}

		ServiceHost WebServiceHost;
		void publishWebService()
		{
			WebServiceHost = new ServiceHost(typeof(BuildDefinitionCollection), new Uri("http://localhost:8085/BuildMonitorServices.asmx"));
			WebServiceHost.AddDefaultEndpoints();
			//WebServiceHost.AddServiceEndpoint(typeof(ITFSEventHandlerService), null, "");
			// Enable metadata publishing.
			ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
			smb.HttpGetEnabled = true;
			smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
			WebServiceHost.Description.Behaviors.Add(smb);
			WebServiceHost.Open();
		}

		ConcurrentStack<BuildDefinitionRow> DirtyList = new ConcurrentStack<BuildDefinitionRow>();
		public void AsyncRefresh()
		{
			AsyncRefresh(Items.ToList());
		}
		public void Exclude(List<BuildDefinitionRow> NutralRows)
		{
			foreach (var row in NutralRows.Where(r=>r.Visible))
			{
				row.Exclude();
			}
		}
		public void Include(List<BuildDefinitionRow> NutralRows)
		{
			foreach (var row in NutralRows.Where(r => !r.Visible))
			{
				row.Include();
			}
		}
		public void CancelRefresh()
		{
			DirtyList.Clear();
		}
		public void AsyncRefresh(List<BuildDefinitionRow> DirtyRows)
		{
			if (DirtyRows.Count == 0)
				return;
			updateAllBuildInQueue();
			foreach (var r in DirtyRows)
			{
				r.IsDirty = true;
			}
			var rows = new List<BuildDefinitionRow>(DirtyRows);
			rows.Reverse();
			DirtyList.PushRange(rows.ToArray());
			if (!bw.IsBusy)
			{
				bw.RunWorkerAsync();
			}
		}
		private void bw_DoWork(object sender, DoWorkEventArgs e)
		{
			Refresh();
		}
		void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
		}
		public void Refresh()
		{
			BuildDefinitionRow item;
			bool itemExists = DirtyList.TryPop(out item);
			while (itemExists)
			{
				item.Refresh();
				itemExists = DirtyList.TryPop(out item);
			}
		}
		public void updateAllBuildInQueue()
		{
			lock (this)
			{
				if (Items.Count > 0)
				{
					if (BuildServer.BuildServerVersion == BuildServerVersion.V3)
					{
						var QBuildSpec = BuildServer.CreateBuildQueueSpec(Items.Select(r => r.BuildDefinitionUri));
						AllBuildInQueue = BuildServer.QueryQueuedBuilds(QBuildSpec).QueuedBuilds;
						Agents = BuildServer.QueryBuildAgents(BuildServer.CreateBuildAgentSpec()).Agents;
					}
					else
					{
						var commonStruct = TeamProjectCollection.GetService<ICommonStructureService>();
						var teamProjectInfos = commonStruct.ListAllProjects();
						//compatible with tfs2008
						AllBuildInQueue = (from p in teamProjectInfos from b in BuildServer.QueryQueuedBuilds(BuildServer.CreateBuildQueueSpec(p.Name)).QueuedBuilds select b).ToArray();
						Agents = (from b in AllBuildInQueue select b.BuildController).ToArray();
					}
					Items.ToList().ForEach(r => r.RefreshQueue());
				}
			}
		}

		public void Dispose()
		{
			if (WebServiceHost != null)
			{
				var x = eventEndpoint.GetAllEventSubscriptions();
				//eventEndpoint.UnsubscribeEvent(tfsEventSubscriptionID);
				var y = eventEndpoint.GetAllEventSubscriptions();
				WebServiceHost.Close();
			}
		}
	}
}
